#include <unistd.h>
#include "stdio.h"
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_pwm.h"
#include "hi_io.h"

#define PWM_PORT HI_PWM_PORT_PWM0  // 使用PWM0端口
#define LED_GPIO 9                // LED连接到GPIO9 (与PWM0复用)
#define PWM_FREQ 1000             // PWM频率1KHz (周期1ms)
#define MIN_DUTY 10               // 最小占空比(1%)
#define MAX_DUTY 990              // 最大占空比(99%)
#define STEP_SIZE 5               // 占空比变化步长
#define DELAY_MS 20               // 亮度变化间隔(ms)

static void BreathLedTask(void *arg)
{
    (void)arg;
    
    // 设置GPIO9为PWM0输出功能
    // HI_IO_FUNC_GPIO_9_PWM0_OUT: GPIO9作为PWM0输出
    hi_io_set_func(LED_GPIO, HI_IO_FUNC_GPIO_9_PWM0_OUT);
    
    // 初始化PWM
    hi_pwm_init(PWM_PORT);
    hi_pwm_set_clock(PWM_CLK_160M);
    
    int current_duty = MIN_DUTY; // 当前占空比
    int direction = 1;           // 1=增加亮度, -1=减小亮度

    while (1) {
        // 设置PWM占空比 (高电平时间 = 占空比值 * 周期 / 1000)
        hi_pwm_start(PWM_PORT, current_duty, PWM_FREQ);
        
        // 更新占空比值
        current_duty += (direction * STEP_SIZE);
        
        // 检查边界并反转方向
        if (current_duty >= MAX_DUTY) {
            current_duty = MAX_DUTY;
            direction = -1;  // 达到最大亮度后开始变暗
        } else if (current_duty <= MIN_DUTY) {
            current_duty = MIN_DUTY;
            direction = 1;   // 达到最暗后开始变亮
        }
        
        // 输出当前状态信息
        float duty_percent = (float)current_duty / 10.0f;
        printf("PWM Duty: %.1f%%\n", duty_percent);
        
        // 延时控制呼吸速度
        usleep(DELAY_MS * 1000);
    }
}


void BreathLedDemo(void)
{
    osThreadAttr_t attr = {
        .name = "BreathLedTask",
        .attr_bits = 0U,                // 任务属性位
        .cb_mem = NULL,                 // 任务控制块内存
        .cb_size = 0U,                  // 任务控制块大小
        .stack_mem = NULL,              // 任务栈内存
        .stack_size = 1024,
        .priority = osPriorityNormal,
    };

    if (osThreadNew((osThreadFunc_t)BreathLedTask, NULL, &attr) == NULL) {
        printf("Failed to create breath LED task!\n");
    }
}

SYS_RUN(BreathLedDemo);